using System;
using System.ComponentModel.DataAnnotations;
using WalkingTec.Mvvm.Core;

namespace HengTong.Model.Db.Hr.Attendance
{
    /// <summary>
    /// 考勤班次人员排班表
    /// </summary>
    /// <remarks>
    /// 记录员工的具体排班信息，支持多种排班场景：
    /// <list type="bullet">
    /// <item><description>自动排班：根据排班规则自动生成</description></item>
    /// <item><description>人工排班：手动调整的排班安排</description></item>
    /// <item><description>请假：员工请假记录</description></item>
    /// <item><description>调休：调休安排</description></item>
    /// <item><description>替班：临时替班安排</description></item>
    /// <item><description>换班：员工间的班次互换</description></item>
    /// </list>
    /// </remarks>
    public class SysAttendanceRecord : BasePoco
    {
        #region 基本信息

        /// <summary>
        /// 获取或设置人员ID
        /// </summary>
        /// <value>排班的目标人员ID，关联到人员主表</value>
        [Display(Name = "排班人员", Description = "排班的目标人员", GroupName = "基本信息")]
        [Required(ErrorMessage = "排班人员不能为空")]
        public Guid? PersonId { get; set; }

        /// <summary>
        /// 获取或设置人员导航属性
        /// </summary>
        /// <value>排班的人员实体信息</value>
        public SysPerson Person { get; set; }

        /// <summary>
        /// 获取或设置考勤组ID
        /// </summary>
        /// <value>关联的考勤班次规则ID，定义工作时间和规则</value>
        [Display(Name = "考勤班次", Description = "关联的考勤班次规则", GroupName = "基本信息")]
        [Required(ErrorMessage = "考勤班次不能为空")]
        public Guid? AttendanceShiftGroupId { get; set; }

        /// <summary>
        /// 获取或设置考勤班次导航属性
        /// </summary>
        /// <value>关联的考勤班次组实体信息</value>
        public SysAttendanceShiftGroup AttendanceShiftGroup { get; set; }

        /// <summary>
        /// 获取或设置班次类型
        /// </summary>
        /// <value>班次类型：正常上班、请假、调休、替班、换班等</value>
        [Display(Name = "班次类型", Description = "班次类型：正常上班、请假、调休、替班、换班等", GroupName = "基本信息")]
        [Required(ErrorMessage = "班次类型不能为空")]
        public ShiftTypeEnum ShiftType { get; set; }

        /// <summary>
        /// 获取或设置排班方式
        /// </summary>
        /// <value>排班方式：自动排班（系统生成）、人工排班（手动调整）、流程排班(流程生产)</value>
        [Display(Name = "排班方式", Description = "排班方式：自动排班（系统生成）、人工排班（手动调整）", GroupName = "基本信息")]
        [Required(ErrorMessage = "排班方式不能为空")]
        public ScheduleTypeEnum ScheduleType { get; set; }

        /// <summary>
        /// 获取或设置班次状态
        /// </summary>
        /// <value>班次状态：正常、取消、暂停等</value>
        [Display(Name = "班次状态", Description = "班次状态：正常、取消、暂停等", GroupName = "基本信息")]
        [Required(ErrorMessage = "班次状态不能为空")]
        public ShiftStatusEnum Status { get; set; } = ShiftStatusEnum.正常;

        /// <summary>
        /// 获取或设置备注信息
        /// </summary>
        /// <value>班次的备注说明，如调整原因、特殊安排等</value>
        [Display(Name = "备注说明", Description = "班次的备注说明，如调整原因、特殊安排等", GroupName = "基本信息")]
        [MaxLength(512, ErrorMessage = "备注说明不能超过512个字符")]
        public string Remark { get; set; }


        /// <summary>
        /// 获取或设置关联单据ID
        /// </summary>
        [Display(Name = "关联单据", Description = "关联的请假、调休等单据ID", GroupName = "基本信息")]
        public Guid? BillId { get; set; }

        #endregion

        #region 时间设置

        /// <summary>
        /// 获取或设置排班日期
        /// </summary>
        /// <value>排班的具体日期</value>
        [Display(Name = "排班日期", Description = "排班的具体日期", GroupName = "时间设置")]
        [Required(ErrorMessage = "排班日期不能为空")]
        public DateOnly ShiftDate { get; set; }

        /// <summary>
        /// 获取或设置上班时间
        /// </summary>
        /// <value>实际的上班时间，可能与班次规则的标准时间不同</value>
        [Display(Name = "上班时间", Description = "实际的上班时间，可能与班次规则的标准时间不同", GroupName = "时间设置")]
        public TimeOnly? StartTime { get; set; }

        /// <summary>
        /// 获取或设置下班时间
        /// </summary>
        /// <value>实际的下班时间，可能与班次规则的标准时间不同</value>
        [Display(Name = "下班时间", Description = "实际的下班时间，可能与班次规则的标准时间不同", GroupName = "时间设置")]
        public TimeOnly? EndTime { get; set; }

        #endregion

        #region 替班信息

        /// <summary>
        /// 获取或设置替班人员ID
        /// </summary>
        /// <value>替班的人员ID，仅在班次类型为替班时有效</value>
        [Display(Name = "替班人员", Description = "替班的人员，仅在班次类型为替班时有效", GroupName = "替班信息")]
        public Guid? SubstitutePersonId { get; set; }

        /// <summary>
        /// 获取或设置替班人员导航属性
        /// </summary>
        /// <value>替班的人员实体信息</value>
        public SysPerson SubstitutePerson { get; set; }

        #endregion

        #region 换班信息

        /// <summary>
        /// 获取或设置换班关联ID
        /// </summary>
        /// <value>换班关联的另一个班次记录ID，用于建立换班关系</value>
        [Display(Name = "换班关联", Description = "换班关联的另一个班次记录，用于建立换班关系", GroupName = "换班信息")]
        public Guid? SwapShiftId { get; set; }

        #endregion

        #region 出勤结果

        /// <summary>
        /// 获取或设置出勤结果
        /// </summary>
        /// <value>考勤计算后的出勤结果状态</value>
        [Display(Name = "出勤结果", Description = "考勤计算后的出勤结果状态", GroupName = "出勤结果")]
        public AttendanceResultEnum AttendanceResult { get; set; } = AttendanceResultEnum.未计算;

        /// <summary>
        /// 获取或设置迟到分钟数
        /// </summary>
        /// <value>迟到的分钟数，0表示未迟到，最大值为1440（24小时）</value>
        [Display(Name = "迟到时长(分钟)", Description = "迟到的分钟数，0表示未迟到", GroupName = "出勤结果")]
        [Range(0, 1440, ErrorMessage = "迟到时长必须在0-1440分钟之间")]
        public int? LateMinutes { get; set; }

        /// <summary>
        /// 获取或设置早退分钟数
        /// </summary>
        /// <value>早退的分钟数，0表示未早退，最大值为1440（24小时）</value>
        [Display(Name = "早退时长(分钟)", Description = "早退的分钟数，0表示未早退", GroupName = "出勤结果")]
        [Range(0, 1440, ErrorMessage = "早退时长必须在0-1440分钟之间")]
        public int? EarlyLeaveMinutes { get; set; }

        /// <summary>
        /// 获取或设置有效工作时长
        /// </summary>
        /// <value>计薪或统计口径的有效工作时长（分钟），用于工资计算和统计</value>
        [Display(Name = "有效工时(分钟)", Description = "计薪或统计口径的有效工作时长，用于工资计算和统计", GroupName = "出勤结果")]
        [Range(0, 100000, ErrorMessage = "有效工时必须在0-100000分钟之间")]
        public int? WorkMinutes { get; set; }

        /// <summary>
        /// 获取或设置缺卡次数
        /// </summary>
        /// <value>当日缺卡（未打卡）的次数，正常情况下应为0</value>
        [Display(Name = "缺卡次数", Description = "当日缺卡（未打卡）的次数，正常情况下应为0", GroupName = "出勤结果")]
        [Range(0, 10, ErrorMessage = "缺卡次数必须在0-10次之间")]
        public int? MissingPunchCount { get; set; }

        /// <summary>
        /// 获取或设置是否存在异常
        /// </summary>
        /// <value>是否存在考勤异常（迟到、早退、缺卡、旷工等）</value>
        [Display(Name = "是否异常", Description = "是否存在考勤异常（迟到、早退、缺卡、旷工等）", GroupName = "出勤结果")]
        public bool IsAbnormal { get; set; }

        #endregion
    }

    /// <summary>
    /// 出勤结果枚举
    /// </summary>
    /// <remarks>
    /// 定义考勤计算后的各种出勤状态结果
    /// </remarks>
    public enum AttendanceResultEnum
    {
        /// <summary>
        /// 未计算：尚未进行考勤计算
        /// </summary>
        [Display(Name = "未计算")] 未计算 = 0,

        /// <summary>
        /// 正常：正常出勤，无异常
        /// </summary>
        [Display(Name = "正常")] 正常 = 1,

        /// <summary>
        /// 迟到：上班时间晚于规定时间
        /// </summary>
        [Display(Name = "迟到")] 迟到 = 2,

        /// <summary>
        /// 早退：下班时间早于规定时间
        /// </summary>
        [Display(Name = "早退")] 早退 = 3,

        /// <summary>
        /// 迟到且早退：既迟到又早退
        /// </summary>
        [Display(Name = "迟到且早退")] 迟到且早退 = 4,

        /// <summary>
        /// 缺卡：未按要求打卡
        /// </summary>
        [Display(Name = "缺卡")] 缺卡 = 5,

        /// <summary>
        /// 旷工：未出勤且无请假记录
        /// </summary>
        [Display(Name = "旷工")] 旷工 = 6,

        /// <summary>
        /// 加班
        /// </summary>
        加班 = 7
    }

    /// <summary>
    /// 班次类型枚举
    /// </summary>
    /// <remarks>
    /// 定义不同的班次安排类型
    /// </remarks>
    public enum ShiftTypeEnum
    {
        /// <summary>
        /// 正常上班：按正常班次安排工作
        /// </summary>
        [Display(Name = "正常上班")] 正常上班 = 1,

        /// <summary>
        /// 请假：员工申请的各类假期
        /// </summary>
        [Display(Name = "请假")] 请假 = 2,

        /// <summary>
        /// 调休：调整休息时间
        /// </summary>
        [Display(Name = "调休")] 调休 = 3,

        /// <summary>
        /// 替班：临时替其他员工上班
        /// </summary>
        [Display(Name = "替班")] 替班 = 4,

        /// <summary>
        /// 换班：与其他员工互换班次
        /// </summary>
        [Display(Name = "换班")] 换班 = 5,

        /// <summary>
        /// 加班：员工在正常工作时间之外的工作
        /// </summary>
        [Display(Name = "加班")] 加班 = 7,

        /// <summary>
        ///  出差：员工因工作需要外出
        /// </summary>
        [Display(Name = "出差")] 出差 = 8
    }

    /// <summary>
    /// 排班方式枚举
    /// </summary>
    /// <remarks>
    /// 定义班次生成的方式
    /// </remarks>
    public enum ScheduleTypeEnum
    {
        /// <summary>
        /// 自动排班：系统根据规则自动生成的排班
        /// </summary>
        [Display(Name = "自动排班")] 自动排班 = 1,

        /// <summary>
        /// 人工排班：管理员手动调整的排班
        /// </summary>
        [Display(Name = "人工排班")] 人工排班 = 2,

        /// <summary>
        /// 流程排班: 流程定义的排班
        /// </summary>
        流程排班 = 3
    }

    /// <summary>
    /// 班次状态枚举
    /// </summary>
    /// <remarks>
    /// 定义班次记录的状态
    /// </remarks>
    public enum ShiftStatusEnum
    {
        /// <summary>
        /// 正常：班次正常有效
        /// </summary>
        [Display(Name = "正常")] 正常 = 1,

        /// <summary>
        /// 取消：班次已被取消
        /// </summary>
        [Display(Name = "取消")] 取消 = 2,

        /// <summary>
        /// 暂停：班次暂时停用
        /// </summary>
        [Display(Name = "暂停")] 暂停 = 3
    }
}